/*
 * ppd.c
 *
 *  Created on: 23/09/2011
 *      Author: utn_so
 */

#include "../../headers/GlobalHeader.h"

extern char* handlerArchivoMapeado;
extern pthread_mutex_t mutexArchivoMapeado;
extern struct_config configuracion;
extern int32_t filesize;
/*
Funcion que abre el archivo fat32 que mapea el disco (Mapping File Into Memory) devolviendo un handler
para poder realizar operaciones de E/S con el archivo.
*/
char* ppd_abrirArchivo(){
	char* discoMapeado;
	//int32_t filesize;
	int32_t descriptorArchivo;
	int32_t retMadvise;

	//Obtengo file descriptor
	descriptorArchivo = open (configuracion.PathArchivo, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);

	//Mapeo el disco
	discoMapeado = mmap(0, filesize*1024,  PROT_READ | PROT_WRITE, MAP_SHARED, descriptorArchivo, 0);

	retMadvise = posix_madvise (discoMapeado, filesize*1024, 2);

	return discoMapeado;
}

PPD_SECTOR_DEVUELVE ppd_leerSector(int32_t sectorARetornar,char* handlerArchivoMapeado){

	PPD_SECTOR_DEVUELVE sectorDevuelto;
	int32_t tiempoLectura=0;

	tiempoLectura=configuracion.TiempoLectura;

	//Copio el valor obtenido en el struct
	pthread_mutex_lock (&mutexArchivoMapeado);
	memcpy(sectorDevuelto.bufferSector,getSector(handlerArchivoMapeado,sectorARetornar),512);
	pthread_mutex_unlock (&mutexArchivoMapeado);

	usleep(tiempoLectura);

	return sectorDevuelto;
}

int32_t ppd_escribirSector(int32_t sectorAEscribir, char* bufferSector,char* handlerArchivoMapeado){

	int32_t valorRetorno=-1;

	int32_t tiempoEscritura=0;

	tiempoEscritura=configuracion.TiempoEscritura;

	pthread_mutex_lock (&mutexArchivoMapeado);
	memcpy(getSector(handlerArchivoMapeado,sectorAEscribir), bufferSector,512);
	pthread_mutex_unlock (&mutexArchivoMapeado);

	//Sincronizo el archivo para que se guarden los cambios
	//valorRetorno=msync(handlerArchivoMapeado, filesize*1024, MS_SYNC );

	usleep(tiempoEscritura);

	return valorRetorno;
}

//Devuelve un handler con el disco apuntando al sector adecuado
char *getSector(char* handlerDiscoMapeado, int32_t sector ){
	return handlerDiscoMapeado + sector * 512;
}

int32_t tamanioDisco(){
	int32_t tamanio=0;
	int32_t cierroDescriptor=0;
	FILE *archivoDisco;

	struct stat buffer;
	int32_t status;

	archivoDisco = open(configuracion.PathArchivo, O_RDWR );
	status = fstat(archivoDisco, &buffer);

	cierroDescriptor=close(archivoDisco);

	tamanio = buffer.st_size / 1024;

	return tamanio;
}

int32_t cantidadTotalDeSectores(){

	 return (configuracion.Cylinders*configuracion.Sectors);

}

int32_t cerrarArchivo(){
	int32_t returnValue;

	returnValue=munmap( handlerArchivoMapeado, filesize*1024);

	return returnValue;
}
